/*
 * ExcelUtil.java
 *
 * 功  能：
 * 类  名：ExcelUtil
 * 版权所有：中兴（沈阳）金融科技有限公司
 *
 *   版本        变更日期             作者      变更内容
 * ────────────────────────────
 *   V1.0        2016年6月24日    hanyx      新建
*/
package org.agile4j.easypoi;

import org.agile4j.easypoi.entity.*;
import org.agile4j.easypoi.utils.FreeMarkerUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.Workbook;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.*;

/**
 * 描述：
 * 
 * @author hanyx
 * @version 1.0
 */
public class ExcelHelper {

	private static final Logger LOGGER = LogManager.getLogger(ExcelHelper.class) ;
	
	private static Map<String, BaseDateEntity> baseDateEntityMap = new HashMap<>() ;
//	private static Map<String, DataDictEntity> dataDictEntityMap = new HashMap<>() ;
	private static Map<String, EnumTypeEntity> enumTypeEntityyMap = new HashMap<>() ;
	private static final String BASETYPE_SUFFIX = "BaseType." ;
	
	public static String xmlPath ;
	public static String excelRootPath ;
	static {
		try {
			String url =ExcelHelper.class.getResource("/").toURI().getPath() ;
			xmlPath = new File(url).getParentFile().getParentFile().getPath() ;
			excelRootPath = xmlPath + File.separator + "src/main/resources" + File.separator + "devtool" + File.separator;
			xmlPath = xmlPath + File.separator + "src/main/resources" + File.separator + "freemarker/xml" + File.separator;
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 导入 基本数据类型 测试用例
	 */
	public static void exportBaseType() throws Exception {
		List<BaseDateEntity> list = new ArrayList<>();
		BaseDateEntity vo = new BaseDateEntity();
		vo.setId("B_DATE");
		vo.setDesc("标准日期类型");
		vo.setMaxLength("10");
		vo.setMinLength("0");
		vo.setScale("2");
		vo.setType("string");
		list.add(vo);

		ExportParams params = new ExportParams(null, "test", ExcelType.XSSF);
		Workbook workbook = ExcelExportUtil.exportExcel(params, BaseDateEntity.class, list);
		FileOutputStream fos = new FileOutputStream("d:/tt.xlsx");
		workbook.write(fos);
		fos.close();
	}

	/**
	 * 导出 基本数据类型 测试用例
	 */
	public static void importBaseType(String fileName, int createFlag) throws Exception {
		ImportParams params = new ImportParams();
		params.setHeadRows(1);
		params.setSheetNum(1);
		File file = new File(excelRootPath + "基础类型.xlsx");
		List<BaseDateEntity> list = ExcelImportUtil.importExcel(file, BaseDateEntity.class, params);
		for (BaseDateEntity vo : list) {
			vo.setType(StringUtils.deleteWhitespace(vo.getType()));
			vo.setId(StringUtils.deleteWhitespace(vo.getId()));
			baseDateEntityMap.put(vo.getId(), vo) ;
		}
		Map<String, List<BaseDateEntity>> dataMap = new HashMap<>() ;
		dataMap.put("baseTypeList", list) ;
		String result = FreeMarkerUtil.buildContent("baseType.ftl", dataMap) ;
		if (createFlag == 1) {	// 只有 createFlag 时 才生成文件
			createXml(result, fileName);	// 生成文件
		}
	}

	/**
	 * 导入 枚举类型 测试用例
	 */
	public static void exportEnumType() throws Exception {
		List<EnumEntity> enumEntityList = new ArrayList<>();
		EnumEntity vo1 = new EnumEntity();
		vo1.setId("YES");
		vo1.setDesc("是");
		vo1.setValue("1");
		enumEntityList.add(vo1);
		
		EnumEntity vo2 = new EnumEntity();
		vo2.setId("NO");
		vo2.setDesc("否");
		vo2.setValue("0");
		enumEntityList.add(vo2);		
		
		List<EnumTypeEntity> list = new ArrayList<>();
		EnumTypeEntity vo = new EnumTypeEntity();
		vo.setEnumTypeid("E_SHIFOUBZ");
		vo.setDesc("是否标志");
		vo.setBaseTypeId("BaseType.U_LEIXIN01");
		vo.setEnumEntityList(enumEntityList);

		list.add(vo);
		
		ExportParams params = new ExportParams(null, "test", ExcelType.XSSF);
		Workbook workbook = ExcelExportUtil.exportExcel(params, EnumTypeEntity.class, list);
		FileOutputStream fos = new FileOutputStream("d:/tt4.xlsx");
		workbook.write(fos);
		fos.close();
	}

	/**
	 * 导出 枚举类型 测试用例
	 */
	public static void importEnumType(String fileName, int createFlag) throws Exception {
		ImportParams params = new ImportParams();
		params.setHeadRows(2);
		params.setSheetNum(5); // 导入5个sheet的数据
		File file = new File(excelRootPath + "枚举.xls");

		List<EnumTypeEntity> list = ExcelImportUtil.importExcel(file, EnumTypeEntity.class, params);
		Map<String, EnumTypeEntity> map1 = new HashMap<>() ;
		for (EnumTypeEntity enumVo: list) {
			map1.put(enumVo.getEnumTypeid(),enumVo) ;
		}

		List<EnumTypeEntity> newList = new ArrayList<>() ;
		for (Map.Entry<String, EnumTypeEntity> entry:map1.entrySet()) {
			newList.add(entry.getValue()) ;
		}
		Iterator<EnumTypeEntity> ite = newList.iterator() ;
		while (ite.hasNext()) {
			EnumTypeEntity vo = ite.next();


			if (baseDateEntityMap.containsKey(StringUtils.replace(vo.getBaseTypeId(), BASETYPE_SUFFIX, ""))) { // 判断枚举对象中的数据类型是否是以存在的数据类型
				for (EnumEntity enumEntity: vo.getEnumEntityList()) {
					if (enumEntity.getId() == null || enumEntity.getValue() == null || enumEntity.getDesc() == null) {
						LOGGER.error("[{}]枚举对象{}的值对象集合有异常.", fileName,vo.getEnumTypeid());
						ite.remove();
						break;
					}
				}
				vo.setEnumTypeid(StringUtils.replace(vo.getEnumTypeid()," ", "_"));
				enumTypeEntityyMap.put(vo.getEnumTypeid(), vo);
			} else { // 不存在的从集合里删除
				LOGGER.error("[{}]枚举对象{}的基本数据类型字段{}是不存在.", fileName, vo.getEnumTypeid(), vo.getBaseTypeId());
				ite.remove();
			}
		}
		Map<String, List<EnumTypeEntity>> dataMap = new HashMap<>() ;
		dataMap.put("enumTypeList", newList) ;
		String result = FreeMarkerUtil.buildContent("enumType.ftl", dataMap) ;
		if (createFlag == 1) {    // 只有 createFlag 时 才生成文件
			createXml(result, fileName);    // 生成文件
		}
	}

	/**
	 * 导入 字典类型 测试用例
	 */
	public static void exportDataDict() throws Exception {
		List<DataDictEntity> list = new ArrayList<>();
		DataDictEntity vo = new DataDictEntity();
		vo.setId("RMB_ITEM");
		vo.setDesc("标准日期类型");
		vo.setEnumTypeId("LOP_TYP");
		vo.setDataType("基本类型");
		vo.setBaseTypeId("B_TYP1");
		list.add(vo);

		ExportParams params = new ExportParams(null, "test", ExcelType.XSSF);
		Workbook workbook = ExcelExportUtil.exportExcel(params, DataDictEntity.class, list);
		FileOutputStream fos = new FileOutputStream("d:/tt1.xlsx");
		workbook.write(fos);
		fos.close();
	}

	/**
	 * 导出 字典类型 测试用例
	 */
	public static void importDataDict(String excelPath, String fileName, int createFlag) throws Exception {
		ImportParams params = new ImportParams();
		params.setHeadRows(1);
		params.setSheetNum(1);
		File file = new File(excelRootPath + excelPath);
		List<DataDictEntity> list = ExcelImportUtil.importExcel(file, DataDictEntity.class, params);


		Map<String, DataDictEntity> map1 = new HashMap<>() ;
		for (DataDictEntity vo: list) {
			map1.put(vo.getId(),vo) ;
		}
		List<DataDictEntity> newList = new ArrayList<>() ;
		newList.addAll(map1.values()) ;

		Iterator<DataDictEntity> ite = newList.iterator() ;
		while (ite.hasNext()) {
			DataDictEntity vo = ite.next();
			if (!baseDateEntityMap.containsKey(vo.getBaseTypeId())) { // 判断字典对象中的数据类型是否是以存在的数据类型
				LOGGER.error("[{}]数据字典对象{}的基本数据类型字段{}是不存在.",fileName, vo.getId(), vo.getBaseTypeId());
				ite.remove();
			} else {
				BaseDateEntity baseDateEntity = baseDateEntityMap.get(vo.getBaseTypeId()) ;
				vo.setType(baseDateEntity.getType());
				vo.setMaxLength(baseDateEntity.getMaxLength()) ;
				vo.setMinLength(baseDateEntity.getMinLength());
				vo.setScale(baseDateEntity.getScale());
				if (StringUtils.equals(vo.getDataType(), "0")) { // 类型是枚举时在判断枚举ID是否已存在
					if (!enumTypeEntityyMap.containsKey(vo.getEnumTypeId())) {
						LOGGER.error("[{}]数据字典对象{}的枚举字段{}是不存在.",fileName, vo.getId(), vo.getEnumTypeId());
						ite.remove();
					}
				}
			}
//			dataDictEntityMap.put(vo.getId(), vo) ;
		}

		Map<String, List<DataDictEntity>> dataMap = new HashMap<>() ;
		for (DataDictEntity vo : newList) {
			vo.setBaseTypeId(BASETYPE_SUFFIX + vo.getBaseTypeId());
			if (StringUtils.contains(vo.getDesc(),"流水号")) {
				LOGGER.debug("{}模块 :收集流水号: 实体:{}", fileName,vo );
			}
		}
		dataMap.put("dictList", newList) ;
		String result = FreeMarkerUtil.buildContent("dataDictionary.ftl", dataMap) ;
		if (createFlag ==1){	// 只有 createFlag 时 才生成文件
			createXml(result, fileName);	// 生成文件
		}
	}

	public static void importMessage(String excelPath, String fileName, int createFlag) throws Exception {
		ImportParams params = new ImportParams();
		params.setHeadRows(1);
		params.setSheetNum(1);
		File file = new File(excelRootPath + excelPath);
		List<MessageEntity> list = ExcelImportUtil.importExcel(file, MessageEntity.class, params);

		// 去重复
		Map<String, MessageEntity> msgMap = new HashMap<>() ;
		for ( MessageEntity vo : list ) {
			msgMap.put(vo.getId(), vo) ;
		}
		List<MessageEntity> newList = new ArrayList<>() ;
		newList.addAll(msgMap.values()) ;

		Map<String, List<MessageEntity>> ftlMap = new HashMap<>() ;
		ftlMap.put("dictList", newList) ;
		String result = FreeMarkerUtil.buildContent("error.ftl", ftlMap) ;
		if (createFlag ==1){	// 只有 createFlag 时 才生成文件
			createXml(result, fileName);	// 生成文件
		}
	}

	public static void exportData() throws Exception {
		exportBaseType();
		exportEnumType();
		exportDataDict();
	}

	private static void createXml(String result, String fileName) throws Exception{
		SAXReader sax = new SAXReader() ;
		InputStream is = new ByteArrayInputStream(result.getBytes()) ;
		Document document = sax.read(is) ;
		OutputFormat format = OutputFormat.createPrettyPrint() ;
		format.setEncoding("UTF-8");
		XMLWriter out = new XMLWriter(new FileOutputStream(new File(xmlPath + fileName)), format) ;
		out.write(document);
	}

	public static void main(String[] args) throws Exception{
		importBaseType("baseType.xml", 1);
		importEnumType("sysEnumType.xml",1);
		importDataDict("公共1\\公共1 - 数据字典.xlsx", "cm1.dataDictionary.xml", 1);
//		importDataDict("公共2\\公共2 - 数据字典.xls", "cm2.dataDictionary.xml", 1);
//		importDataDict("存款\\存款 - 数据字典.xlsx", "dp.dataDictionary.xml", 1);
//		importDataDict("贷款\\贷款 - 数据字典.xls", "cl.dataDictionary.xml", 1);
//		importDataDict("会计\\会计 - 数据字典.xlsx", "gl.dataDictionary.xml", 1);

//		importMessage("会计\\会计 - 异常.xlsx", "gl.dataDictionary.xml", 1);
	}
}
